package cn.thornbird.orgsync.service.impl;

import cn.thornbird.orgsync.entity.status.ExecuteStatus;
import cn.thornbird.orgsync.model.statistic.DateStatisticItem;
import cn.thornbird.orgsync.model.statistic.StatisticData;
import cn.thornbird.orgsync.model.UserData;
import cn.thornbird.orgsync.model.statistic.TaskStatisticData;
import cn.thornbird.orgsync.repository.*;
import cn.thornbird.orgsync.service.StatisticService;
import cn.thornbird.orgsync.util.DateUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@AllArgsConstructor
public class StatisticServiceImpl implements StatisticService {

    private final UserRepository userRepository;

    private final CompanyRepository companyRepository;

    private final CertificateDetailRepository certificateDetailRepository;

    private final TaskRepository taskRepository;

    private final TaskDetailRepository taskDetailRepository;

    @Override
    public StatisticData getStatisticData(UserData userData) {
        StatisticData statisticData = new StatisticData();
        if (userData.isSuperuser()) {
            statisticData.setUserCount(userRepository.count());
            statisticData.setActiveUserCount(userRepository.countByActive(true));
            statisticData.setCompanyCount(companyRepository.count());
            statisticData.setActiveCompanyCount(companyRepository.countByActive(true));
            statisticData.setCertificateCount(certificateDetailRepository.count());
            statisticData.setTaskCount(taskRepository.count());
            statisticData.setActiveTaskCount(taskRepository.countByActive(true));
        }
        return statisticData;
    }

    @Override
    public TaskStatisticData getTaskStatisticData(UserData userData, Date startDate, Date endDate) {
        Date yesterday = DateUtil.getYesterday(new Date());
        Date minStartDate = DateUtil.addYears(yesterday, -3);
        if (startDate == null) {
            startDate = yesterday;
        }
        if (endDate == null) {
            endDate = yesterday;
        }
        startDate = startDate.compareTo(yesterday) > 0 ? yesterday : startDate;
        endDate = endDate.compareTo(yesterday) > 0 ? yesterday : endDate;
        if (minStartDate.compareTo(startDate) > 0) {
            startDate = minStartDate;
        }

        TaskStatisticData data = new TaskStatisticData();
        data.setDates(new ArrayList<>());
        data.setTaskCounts(new ArrayList<>());
        data.setCounts(new ArrayList<>());
        data.setCreatedCounts(new ArrayList<>());
        data.setStartedCounts(new ArrayList<>());
        data.setEndedCounts(new ArrayList<>());
        data.setErrorCounts(new ArrayList<>());
        Map<Long, Integer> dateMap = new HashMap<>();
        long days = DateUtil.daysBetween(startDate, endDate) + 1;
        Date date = startDate;
        for (int i = 0; i < days; i++) {
            data.getDates().add(DateUtil.formatDate(date, DateUtil.DATE_FORMAT));
            data.getTaskCounts().add(0L);
            data.getCounts().add(0L);
            data.getCreatedCounts().add(0L);
            data.getStartedCounts().add(0L);
            data.getEndedCounts().add(0L);
            data.getErrorCounts().add(0L);
            dateMap.put(date.getTime(), i);
            date = DateUtil.addDays(date, 1);
        }

        List<DateStatisticItem> taskCounts = taskDetailRepository.countByTaskIdAndDateRange(startDate, endDate);
        for (DateStatisticItem item : taskCounts) {
            int index = dateMap.get(item.getDate().getTime());
            data.getTaskCounts().set(index, item.getTotal());
        }
        List<DateStatisticItem> counts = taskDetailRepository.countByDateRange(startDate, endDate);
        for (DateStatisticItem item : counts) {
            int index = dateMap.get(item.getDate().getTime());
            data.getCounts().set(index, item.getTotal());
        }
        List<DateStatisticItem> createdCounts = taskDetailRepository.countByExecuteStatusAndDateRange(
                ExecuteStatus.Created.getValue(), startDate, endDate);
        for (DateStatisticItem item : createdCounts) {
            int index = dateMap.get(item.getDate().getTime());
            data.getCreatedCounts().set(index, item.getTotal());
        }
        List<DateStatisticItem> startedCounts = taskDetailRepository.countByExecuteStatusAndDateRange(
                ExecuteStatus.Started.getValue(), startDate, endDate);
        for (DateStatisticItem item : startedCounts) {
            int index = dateMap.get(item.getDate().getTime());
            data.getStartedCounts().set(index, item.getTotal());
        }
        List<DateStatisticItem> endedCounts = taskDetailRepository.countByExecuteStatusAndDateRange(
                ExecuteStatus.Ended.getValue(), startDate, endDate);
        for (DateStatisticItem item : endedCounts) {
            int index = dateMap.get(item.getDate().getTime());
            data.getEndedCounts().set(index, item.getTotal());
        }
        List<DateStatisticItem> errorCounts = taskDetailRepository.countByExecuteStatusAndDateRange(
                ExecuteStatus.Error.getValue(), startDate, endDate);
        for (DateStatisticItem item : errorCounts) {
            int index = dateMap.get(item.getDate().getTime());
            data.getErrorCounts().set(index, item.getTotal());
        }

        return data;
    }

}
